package com.gitee.wsl.android.ui.recyclerView.adapter

import android.util.SparseArray
import android.util.SparseBooleanArray
import android.view.View
import androidx.recyclerview.widget.RecyclerView

interface ActionRepository<T>

object Action {

    interface ClickAction<T> : com.gitee.wsl.android.ui.recyclerView.adapter.ActionRepository<T> {
        fun onClick(v: View,position: Int,item:T?)
        fun onLongClick(v: View,position: Int,item:T?){}
    }

    interface SelectAction<T> : com.gitee.wsl.android.ui.recyclerView.adapter.ActionRepository<T> {
        fun onSelectClick(position: Int,item:T?)
    }

    interface CRUDAction<T> : com.gitee.wsl.android.ui.recyclerView.adapter.ActionRepository<T> {

        fun updateItem(item:T){}

        fun deleteItem(item:T){}

    }
}


interface SelectHelperScope<T:Any>{
    fun notifyItemChanged(position: Int)
}


interface SelectHelperAction<T:Any>:
    com.gitee.wsl.android.ui.recyclerView.adapter.ActionRepository<T> {

    fun setSelectableMaxSize(size: Int)

    fun isSelected(position: Int):Boolean

    fun clearSelection()

    fun getSelectedItems(): List<Int>

    fun toggleSelection(
        position: Int,
        isMaxSelect: ((Boolean) -> Unit)? = null
    )

    fun isMultiSelect():Boolean

    fun getSelectedCount():Int

    fun setMultiSelectable(enable: Boolean)

    fun dataItemInsert(position: Int)

    fun dataItemRemoved(position: Int)

    fun reset()
}

open class SampleSelectHelper<T:Any>(val callBack: com.gitee.wsl.android.ui.recyclerView.adapter.SelectHelperScope<T>, isMultiSelect:Boolean=true):
    com.gitee.wsl.android.ui.recyclerView.adapter.SelectHelperAction<T>,
    RecyclerView.AdapterDataObserver() {
    private val selectedItems = SparseBooleanArray()
    private val selectConfigCache = SparseArray<SparseArray<Any>>()

    private val defaultSelectedConfig by lazy {
        SparseArray<Any>().apply {
            append(0, isMultiSelect) // is Multi Selectable
            append(1, Int.MAX_VALUE) // Selectable Max Size Default Int.Max
        }
    }

     val selectedMaxSize: Int
        get() = getSelectConfig(hashCode())[1] as Int


    override fun isMultiSelect(): Boolean=getSelectConfig(hashCode())[0] as Boolean

    override fun getSelectedCount(): Int = selectedItems.size()

    private fun getSelectConfig(key: Int): SparseArray<Any> {
        return selectConfigCache[key] ?: defaultSelectedConfig.apply {
            selectConfigCache.append(key, this)
        }
    }

    override fun setMultiSelectable(enable: Boolean) {
        getSelectConfig(hashCode()).setValueAt(0, enable)
        if (!enable && getSelectedCount() > 1) {
            clearSelection()
        }
    }

    override fun setSelectableMaxSize(size: Int) {
        getSelectConfig(hashCode()).setValueAt(1, size)
    }

    override fun getSelectedItems(): List<Int> {
        val itemSize = selectedItems.size()
        val items: MutableList<Int> = ArrayList(itemSize)
        for (i in 0 until itemSize) {
            items.add(selectedItems.keyAt(i))
        }
        return items
    }

    override fun isSelected(position: Int) = getSelectedItems().contains(position)

    override fun clearSelection() {
        val selection = getSelectedItems()
        selectedItems.clear()
        for (i in selection) {
            callBack.notifyItemChanged(i)
        }
    }

    override fun toggleSelection(
        position: Int,
        isMaxSelect: ((Boolean) -> Unit)?
    ) {
        val si = selectedItems
        val isSelect = si.get(position, false)
        if (getSelectedCount() >= selectedMaxSize && !isSelect) {
            isMaxSelect?.invoke(true)
            return
        }
        isMaxSelect?.invoke(false)
        if (!isMultiSelect()) {
            clearSelection()
        }
        if (isSelect) {
            si.delete(position)
        } else {
            si.put(position, true)
        }
        callBack.notifyItemChanged(position)
    }

    override fun dataItemInsert(position: Int) {
        selectedItems.append(position,false)
    }

    /**
     * 方案 有点 不行,
     */
    override fun dataItemRemoved(position: Int) {
        if(getSelectedItems().contains(position))
           selectedItems.removeAt(position)
    }

    override fun reset() {
        selectedItems.clear()
    }

    override fun onChanged() {
        reset()
    }

    override fun onItemRangeInserted(positionStart: Int, itemCount: Int) {
       (0 until  itemCount).forEach {
           dataItemInsert(positionStart)
       }
    }

    override fun onItemRangeRemoved(positionStart: Int, itemCount: Int) {
        val itemList=getSelectedItems()
        val endPosition = positionStart+itemCount
        (  0 until itemCount  ).forEach {
            if(itemList.contains(it))
                selectedItems.removeAt(endPosition-it)
        }
    }

    override fun onItemRangeMoved(fromPosition: Int, toPosition: Int, itemCount: Int) {
        (0 until itemCount).forEach {
            val fromPositionSelect = selectedItems.get(fromPosition+it, false)
            val toPositionSelect = selectedItems.get(toPosition+it, false)
            selectedItems.put(fromPosition+it,toPositionSelect)
            selectedItems.put(toPosition+it,fromPositionSelect)
        }
    }
}

